Built-up Index · Urban Mapping

BI – Built-up Index (NDBI − NDVI)

BI is a composite urban index that combines NDBI (built-up signal) and NDVI (vegetation signal) by subtracting NDVI from NDBI. This enhances dense built-up and impervious areas while suppressing vegetation.

1. Scientific Definition

The Built-up Index (BI) enhances urban areas by combining the Normalized Difference Built-up Index (NDBI) with the Normalized Difference Vegetation Index (NDVI): built-up pixels tend to have high NDBI and low NDVI, while vegetated pixels show the opposite.

Formula

BI = NDBI − NDVI
NDBI = (SWIR − NIR) / (SWIR + NIR)
NDVI = (NIR − RED) / (NIR + RED) Theoretical range: −2 → +2 (most values within −1 → +1)

  • NIR – Near InfraRed reflectance
  • SWIR – Short-Wave InfraRed reflectance (SWIR1)
  • RED – Red band reflectance

Typical Interpretation

BIInterpretation
< 0Water / dense vegetation, non-built-up
0 – 0.2Mixed pixels / low-density built-up
0.2 – 0.5Moderate built-up / suburban
> 0.5Dense urban / strongly impervious surfaces

Main Applications

  • Urban expansion and densification mapping
  • Separating dense built-up from vegetated / peri-urban areas
  • Supporting urban heat island and surface temperature studies
  • Feeding into composite environmental indices (e.g. dryness / RSEI)

2. Data & Bands

Sentinel-2 (Recommended)

  • NIR: B8 (~842 nm)
  • RED: B4 (~665 nm)
  • SWIR (SWIR1): B11 (~1610 nm)

Landsat 8 / 9

  • NIR: B5
  • RED: B4
  • SWIR1: B6

Landsat 5 TM / 7 ETM+

  • NIR: B4
  • RED: B3
  • SWIR1: B5

Best Practices

  • Use surface reflectance products (SR).
  • Mask clouds & cloud shadows using QA bands.
  • Always compute NDVI and NDBI first, then derive BI = NDBI − NDVI.
  • Combine BI with land cover or NDWI / MNDWI to separate urban, bare soil and water.
  • Use thresholding or clustering to map built-up density classes.

Suggested Palette

[ "#0b1020", "#1f2937", "#4b6cb7", "#f0b429", "#f97316", "#facc15" ]

3. Google Earth Engine Code – BI (NDBI − NDVI)

// BI using Sentinel-2 SR
// BI = NDBI - NDVI
// NDBI = (SWIR - NIR) / (SWIR + NIR)
// NDVI = (NIR - RED) / (NIR + RED)
// Here: SWIR = B11, NIR = B8, RED = B4

var roi = geometry;   // Draw AOI as 'geometry'
Map.centerObject(roi, 11);

// 1. Load Sentinel-2 surface reflectance
var s2 = ee.ImageCollection("COPERNICUS/S2_SR")
  .filterBounds(roi)
  .filterDate("2023-01-01", "2023-12-31")
  .filter(ee.Filter.lt("CLOUDY_PIXEL_PERCENTAGE", 20))
  .select(["B4","B8","B11"]); // RED, NIR, SWIR

// 2. Median composite
var img = s2.median().clip(roi);

// 3. Compute NDBI and NDVI
var ndbi = img.expression(
  "(S - N) / (S + N)",
  {
    "S": img.select("B11"), // SWIR
    "N": img.select("B8")   // NIR
  }
).rename("NDBI");

var ndvi = img.expression(
  "(N - R) / (N + R)",
  {
    "N": img.select("B8"),  // NIR
    "R": img.select("B4")   // RED
  }
).rename("NDVI");

// 4. Compute BI = NDBI - NDVI
var bi = ndbi.subtract(ndvi).rename("BI");

// 5. Visualization
var vis = {
  min: -1,
  max: 1,
  palette: ["#0b1020","#1f2937","#4b6cb7","#f0b429","#f97316","#facc15"]
};

Map.addLayer(bi, vis, "BI (NDBI − NDVI)");

// Optional: threshold for dense built-up (e.g. BI > 0.3)
var builtup = bi.gt(0.3).selfMask();
Map.addLayer(builtup, {palette:["#facc15"]}, "Built-up mask (BI > 0.3)");

// 6. Export BI as GeoTIFF
Export.image.toDrive({
  image: bi,
  description: "BI_Sentinel2",
  fileNamePrefix: "BI_S2",
  region: roi,
  scale: 20,        // use 20 m to match SWIR resolution
  crs: "EPSG:4326",
  maxPixels: 1e13
});